#ifndef _RCC_H_
#define _RCC_H_

#include "soc.h"

typedef struct {
	uint32_t APB1;  /* 低速外设，最大42MHz */
	uint32_t APB2;  /* 高速外设，最大84MHz */
	uint32_t AHB;   /* 高级外设，最大168MHz，使用以太网时，AHB应大于25MHz */
	uint32_t AHB2;
} RCC_ClkStruct;

typedef enum {
	RCC_RST_AHB1_GPIOA  = (0x1U<<0),
	RCC_RST_AHB1_GPIOB  = (0x1U<<1),
	RCC_RST_AHB1_GPIOC  = (0x1U<<2),
	RCC_RST_AHB1_GPIOD  = (0x1U<<3),
	RCC_RST_AHB1_GPIOE  = (0x1U<<4),
	RCC_RST_AHB1_GPIOF  = (0x1U<<5),
	RCC_RST_AHB1_GPIOG  = (0x1U<<6),
	RCC_RST_AHB1_GPIOH  = (0x1U<<7),
	RCC_RST_AHB1_GPIOI  = (0x1U<<8),
	RCC_RST_AHB1_CRC    = (0x1U<<12),
	RCC_RST_AHB1_DMA1   = (0x1U<<21),
	RCC_RST_AHB1_DMA2   = (0x1U<<22),
	RCC_RST_AHB1_ETHMAC = (0x1U<<25),
	RCC_RST_AHB1_OTGHS  = (0x1U<<29),
} RCC_RstAhb1Enum;

typedef enum {
	RCC_RST_AHB2_DCMI  = (0x1U<<0),
	RCC_RST_AHB2_CRYP  = (0x1U<<4),
	RCC_RST_AHB2_HASH  = (0x1U<<5),
	RCC_RST_AHB2_RNG   = (0x1U<<6),
	RCC_RST_AHB2_OTGFS = (0x1U<<7),
} RCC_RstAhb2Enum;

typedef enum {
	RCC_RST_AHB3_FSMC  = (0x1U<<0),
} RCC_RstAhb3Enum;

typedef enum {
	RCC_RST_APB1_TIM2  = (0x1U<<0),
	RCC_RST_APB1_TIM3  = (0x1U<<1),
	RCC_RST_APB1_TIM4  = (0x1U<<2),
	RCC_RST_APB1_TIM5  = (0x1U<<3),
	RCC_RST_APB1_TIM6  = (0x1U<<4),
	RCC_RST_APB1_TIM7  = (0x1U<<5),
	RCC_RST_APB1_TIM12 = (0x1U<<6),
	RCC_RST_APB1_TIM13 = (0x1U<<7),
	RCC_RST_APB1_TIM14 = (0x1U<<8),
	RCC_RST_APB1_WWDG  = (0x1U<<11),
	RCC_RST_APB1_SPI2  = (0x1U<<14),
	RCC_RST_APB1_SPI3  = (0x1U<<15),
	RCC_RST_APB1_UART2 = (0x1U<<17),
	RCC_RST_APB1_UART3 = (0x1U<<18),
	RCC_RST_APB1_UART4 = (0x1U<<19),
	RCC_RST_APB1_UART5 = (0x1U<<20),
	RCC_RST_APB1_I2C1  = (0x1U<<21),
	RCC_RST_APB1_I2C2  = (0x1U<<22),
	RCC_RST_APB1_I2C3  = (0x1U<<23),
	RCC_RST_APB1_CAN1  = (0x1U<<25),
	RCC_RST_APB1_CAN2  = (0x1U<<26),
	RCC_RST_APB1_PWR   = (0x1U<<28),
	RCC_RST_APB1_DAC   = (0x1U<<29),
} RCC_RstApb1Enum;

typedef enum {
	RCC_RST_APB2_TIM1    = (0x1U<<0),
	RCC_RST_APB2_TIM8    = (0x1U<<1),
	RCC_RST_APB2_USART1  = (0x1U<<4),
	RCC_RST_APB2_USART6  = (0x1U<<5),
	RCC_RST_APB2_ADC     = (0x1U<<8),  /* 所有ADC共用 */
	RCC_RST_APB2_SDIO    = (0x1U<<11),
	RCC_RST_APB2_SPI1    = (0x1U<<12),
	RCC_RST_APB2_SYSCFG  = (0x1U<<14),
	RCC_RST_APB2_TIM9    = (0x1U<<16),
	RCC_RST_APB2_TIM10   = (0x1U<<17),
	RCC_RST_APB2_TIM11   = (0x1U<<18),
} RCC_RstApb2Enum;

typedef enum {
	RCC_CLK_AHB1_GPIOA    = (0x1U<<0),
	RCC_CLK_AHB1_GPIOB    = (0x1U<<1),
	RCC_CLK_AHB1_GPIOC    = (0x1U<<2),
	RCC_CLK_AHB1_GPIOD    = (0x1U<<3),
	RCC_CLK_AHB1_GPIOE    = (0x1U<<4),
	RCC_CLK_AHB1_GPIOF    = (0x1U<<5),
	RCC_CLK_AHB1_GPIOG    = (0x1U<<6),
	RCC_CLK_AHB1_GPIOH    = (0x1U<<7),
	RCC_CLK_AHB1_GPIOI    = (0x1U<<8),
	RCC_CLK_AHB1_CRC      = (0x1U<<12),
	RCC_CLK_AHB1_BKPSRAM  = (0x1U<<18),
	RCC_CLK_AHB1_CCM      = (0x1U<<20),  /* 默认使能 */
	RCC_CLK_AHB1_DMA1     = (0x1U<<21),
	RCC_CLK_AHB1_DMA2     = (0x1U<<22),
	RCC_CLK_AHB1_MAC      = (0x1U<<25),
	RCC_CLK_AHB1_MAC_TX   = (0x1U<<26),
	RCC_CLK_AHB1_MAC_RX   = (0x1U<<27),
	RCC_CLK_AHB1_MAC_PTP  = (0x1U<<28),
	RCC_CLK_AHB1_OTGHS    = (0x1U<<29),
	RCC_CLK_AHB1_OTGHS_ULPI = (0x1U<<30),
	RCC_CLK_AHB1_ALL      = 0x7E7411FF,
} RCC_ClkAhb1Enum;

typedef enum {
	RCC_CLK_AHB2_DCMI  = (0x1U<<0),
	RCC_CLK_AHB2_CRYP  = (0x1U<<4),
	RCC_CLK_AHB2_HASH  = (0x1U<<5),
	RCC_CLK_AHB2_RNG   = (0x1U<<6),
	RCC_CLK_AHB2_OTGFS = (0x1U<<7),
	RCC_CLK_AHB2_ALL   = 0xF1,
} RCC_ClkAhb2Enum;

typedef enum {
	RCC_CLK_AHB3_FSMC  = (0x1U<<0),
	RCC_CLK_AHB3_ALL   = 0x1,
} RCC_ClkAhb3Enum;

typedef enum {
	RCC_CLK_APB1_TIM2  = (0x1U<<0),
	RCC_CLK_APB1_TIM3  = (0x1U<<1),
	RCC_CLK_APB1_TIM4  = (0x1U<<2),
	RCC_CLK_APB1_TIM5  = (0x1U<<3),
	RCC_CLK_APB1_TIM6  = (0x1U<<4),
	RCC_CLK_APB1_TIM7  = (0x1U<<5),
	RCC_CLK_APB1_TIM12 = (0x1U<<6),
	RCC_CLK_APB1_TIM13 = (0x1U<<7),
	RCC_CLK_APB1_TIM14 = (0x1U<<8),
	RCC_CLK_APB1_WWDG  = (0x1U<<11),
	RCC_CLK_APB1_SPI2  = (0x1U<<14),
	RCC_CLK_APB1_SPI3  = (0x1U<<15),
	RCC_CLK_APB1_UART2 = (0x1U<<17),
	RCC_CLK_APB1_UART3 = (0x1U<<18),
	RCC_CLK_APB1_UART4 = (0x1U<<19),
	RCC_CLK_APB1_UART5 = (0x1U<<20),
	RCC_CLK_APB1_I2C1  = (0x1U<<21),
	RCC_CLK_APB1_I2C2  = (0x1U<<22),
	RCC_CLK_APB1_I2C3  = (0x1U<<23),
	RCC_CLK_APB1_CAN1  = (0x1U<<25),
	RCC_CLK_APB1_CAN2  = (0x1U<<26),
	RCC_CLK_APB1_PWR   = (0x1U<<28),
	RCC_CLK_APB1_DAC   = (0x1U<<29),
	RCC_CLK_APB1_ALL   = 0x36FEC9FF,
} RCC_ClkApb1Enum;

typedef enum {
	RCC_CLK_APB2_TIM1    = (0x1U<<0),
	RCC_CLK_APB2_TIM8    = (0x1U<<1),
	RCC_CLK_APB2_USART1  = (0x1U<<4),
	RCC_CLK_APB2_USART6  = (0x1U<<5),
	RCC_CLK_APB2_ADC1    = (0x1U<<8),
	RCC_CLK_APB2_ADC2    = (0x1U<<9),
	RCC_CLK_APB2_ADC3    = (0x1U<<10),
	RCC_CLK_APB2_SDIO    = (0x1U<<11),
	RCC_CLK_APB2_SPI1    = (0x1U<<12),
	RCC_CLK_APB2_SYSCFG  = (0x1U<<14),
	RCC_CLK_APB2_TIM9    = (0x1U<<16),
	RCC_CLK_APB2_TIM10   = (0x1U<<17),
	RCC_CLK_APB2_TIM11   = (0x1U<<18),
	RCC_CLK_APB2_ALL     = 0x75F33,
} RCC_ClkApb2Enum;

/**
 * 复位外设
 */
void RCC_ResetAhb1(RCC_RstAhb1Enum ahb1);
void RCC_ResetAhb2(RCC_RstAhb2Enum ahb2);
void RCC_ResetAhb3(RCC_RstAhb3Enum ahb3);
void RCC_ResetApb1(RCC_RstApb1Enum apb1);
void RCC_ResetApb2(RCC_RstApb2Enum apb2);

/**
 * 使能外设时钟
 */
void RCC_EnableAhb1(RCC_ClkAhb1Enum ahb1);
void RCC_EnableAhb2(RCC_ClkAhb2Enum ahb2);
void RCC_EnableAhb3(RCC_ClkAhb3Enum ahb3);
void RCC_EnableApb1(RCC_ClkApb1Enum apb1);
void RCC_EnableApb2(RCC_ClkApb2Enum apb2);

/**
 * 关闭外设时钟
 */
void RCC_DisableAhb1(RCC_ClkAhb1Enum ahb1);
void RCC_DisableAhb2(RCC_ClkAhb2Enum ahb2);
void RCC_DisableAhb3(RCC_ClkAhb3Enum ahb3);
void RCC_DisableApb1(RCC_ClkApb1Enum apb1);
void RCC_DisableApb2(RCC_ClkApb2Enum apb2);

#endif /* _RCC_H_ */
